package managedbean.tourist;

import entity.CuisinePrefEntity;
import entity.InterestPrefEntity;
import exception.ExistException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.PhaseEvent;
import managedbean.PageRedirectorBean;
import org.primefaces.model.MenuModel;
import session.stateless.SystemMessagesBean;
import session.stateless.TouristAccountSessionBean;
import util.entityhelper.TouristAccountState;
import util.enumeration.Country;
import util.enumeration.CuisineType;
import util.enumeration.Gender;
import util.enumeration.Interest;
import util.generator.TouristMenuGenerator;
import util.localization.WebLocalization;

/**
 *
 * @author Swee Zhi
 */
@ManagedBean
@RequestScoped
public class TouristEditMyFoodSageManagedBean implements Serializable {
    @EJB
    private TouristAccountSessionBean touristAccountMgr;
    // EXCEPTION
    @EJB
    private SystemMessagesBean systemMessages;
    
    // use entity helpers to extract data (attribute extraction and formatting instead of entity in this open bean)
    private TouristAccountState touristAcctState;
    
    // fields for this bean
    private FacesContext ctx = FacesContext.getCurrentInstance();
    private WebLocalization localization;
    private PageRedirectorBean redirect;
    
    // fields passed from session
    private Long touristAccountId;
    private String preferredLocale;
    
    // other fields from database (+ display)
    private String username;
    private String currentPassword;
    private String lastname;
    private String firstname;
    private String gender;
    private String birthdate;
    private Country country;
    private String language;
    private String email;
    private String emailSecondary;
    private List<CuisineType> cuisineTypeList;
    private List<Interest> interestList;
    
    // display only
    private String name;
    private String newPassword;
    private String confirmPassword;
    private MenuModel touristMainMenuModel;
    private MenuModel touristNavMenuModel;
    
    
    public TouristEditMyFoodSageManagedBean() {
        /* LOCALIZATION */
        localization = new WebLocalization();
        preferredLocale = localization.getPreferredLocaleFromSession();
        /* END LOCALIZATION */
        
        redirect = new PageRedirectorBean();
       
        /* pre-load values from session and database */
        // get account ID values from session
        if (ctx.getExternalContext().getSessionMap().containsKey("touristAccountId")) {
            touristAccountId = (Long) ctx.getExternalContext().getSessionMap().get("touristAccountId");
            // put back the session IDs taken
            ctx.getExternalContext().getSessionMap().put("touristAccountId", touristAccountId);
        }
        else {
            // redirect back to login
            redirect.goTouristLoginPageAtPreviousLevel();
        }
        /* END load values from session and database */    
    }
    
    public void initView(PhaseEvent event) {
        /* LOCALIZATION */
        localization = new WebLocalization();
        preferredLocale = localization.getPreferredLocaleFromSession();
        /* END LOCALIZATION */
        
        try {
            // set language for all MANAGERS for all THROWABLE EXCEPTIONS in backend
            // to use this line everytime possible language changes
            touristAccountMgr.setSelectedLocale(preferredLocale);
            // get data from backend, exception alrd thrown by backend if these methods fail.
            
            touristAcctState = touristAccountMgr.getTouristAccountByID(touristAccountId);
            
            username = touristAcctState.getUsername();
            
            lastname = touristAcctState.getTourist().getLastName();
            firstname = touristAcctState.getTourist().getFirstName();
            name = lastname + " " + firstname;
            
            Gender savedGender = touristAcctState.getTourist().getGender();
            gender = localization.getLocalizedGender(savedGender);
            
            Date savedBirthdate = touristAcctState.getTourist().getBirthdate();
            birthdate = localization.getLocalizedDateFormat(savedBirthdate);
            
            Country savedCountry = touristAcctState.getTourist().getCountry();
            if (country == null) {
                country = savedCountry;
            }
            
            String savedLocale = touristAcctState.getTourist().getLocale();
            if (language == null) {
                language = savedLocale;
            }
            
            email = touristAcctState.getTourist().getEmail();
            
            if (emailSecondary == null) {
                emailSecondary = touristAcctState.getTourist().getEmailSecondary();
            }
            
            if (cuisineTypeList == null) {
                this.cuisineTypeList = new ArrayList<CuisineType>();
                
                List<CuisinePrefEntity> cuisineTypes = touristAcctState.getTourist().getPersonalPref().getCuisinePrefs();
                for (int i = 0; i < cuisineTypes.size(); i++) {
                    cuisineTypeList.add(cuisineTypes.get(i).getCuisineType());
                }
            }
            
            if (interestList == null) {
                this.interestList = new ArrayList<Interest>();
                
                List<InterestPrefEntity> interests = touristAcctState.getTourist().getPersonalPref().getInterestPrefs();
                for (int i = 0; i < interests.size(); i++) {
                    //arraylist add the values
                    interestList.add(interests.get(i).getInterest());
                }
            }
            
            // main menu 
            TouristMenuGenerator menuGeneratorMain = new TouristMenuGenerator();
            touristMainMenuModel = menuGeneratorMain.generateTouristMainMenu();
            // nav menu
            TouristMenuGenerator menuGeneratorNav = new TouristMenuGenerator();
            touristNavMenuModel = menuGeneratorNav.generateTouristNavMenu();
        }
        catch (ExistException ex) {
//            System.out.println(ex.getMessage());
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, ex.getMessage(), ""));
        }
        catch (Exception ex) {
            ex.printStackTrace();
//            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, ex.getMessage(), ""));
        }
    }
    
    public void updateTouristDetails(ActionEvent event) {
        /* LOCALIZATION */
        localization = new WebLocalization();
        preferredLocale = localization.getPreferredLocaleFromSession();
        /* END LOCALIZATION */
        
        boolean passwordCheckOK = false;
        boolean hasNewUpdate = false;
        boolean hasPreferenceUpdate = false;
        boolean passwordChecking = false;
        String statusMessage = "";
        
        try {
            // set language for all MANAGERS for all THROWABLE EXCEPTIONS in backend
            // to use this line everytime possible language changes
            touristAccountMgr.setSelectedLocale(preferredLocale);

            // TODO: if can reach til this page it means account ID exists.. can set error for further safety message when free
            touristAcctState = touristAccountMgr.getTouristAccountByID(touristAccountId);

            /* do all necessary checks and set values before UPDATE */
            // check password fields if edited..set back to current password if nothing..
            String latestPassword = touristAcctState.getPassword();
            if (currentPassword.isEmpty()) {
                passwordChecking = true;
                
                if (!newPassword.isEmpty()) {
                    statusMessage = systemMessages.getSystemMessage("CURRENT_PASSWORD_REQUIRED", preferredLocale);
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMessage, ""));
                    passwordCheckOK = false;
                }
            }
            else {
                passwordChecking = true;
                if (newPassword.isEmpty()) {
                    statusMessage = systemMessages.getSystemMessage("NEW_PASSWORD_REQUIRED", preferredLocale);
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMessage, ""));
                    passwordCheckOK = false;
                }
                else {
                    if (currentPassword.equals(touristAcctState.getPassword())) {
                        latestPassword = newPassword;
                        passwordCheckOK = true;
                    }
                    else {
                        statusMessage = systemMessages.getSystemMessage("CURRENT_PASSWORD_INCORRECT", preferredLocale);
                        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, statusMessage, ""));
                        passwordCheckOK = false;
                    }
                }
            }
            
            if (passwordCheckOK == true) {
                hasNewUpdate = true;
            }
            
            // language just retrieve as it is because it is dropdown list
            if (language.equals(touristAcctState.getTourist().getLocale())) {
                // no change
                language = touristAcctState.getTourist().getLocale();
            }
            else {
                hasNewUpdate = true;
            }
            
            // country just retrieve as it is because it is dropdown list
            if (country.equals(touristAcctState.getTourist().getCountry())) {
                // no change
                country = touristAcctState.getTourist().getCountry();
            }
            else {
                hasNewUpdate = true;
            }
            
            // emailSecondary just retrieve as it is because if as it is means user no change else del on purpose
            if (emailSecondary.equals(touristAcctState.getTourist().getEmailSecondary())) {
                // no change
                emailSecondary = touristAcctState.getTourist().getEmailSecondary();
            }
            else {
                hasNewUpdate = true;
            }
            
            List<CuisinePrefEntity> newCuisinePrefList = new ArrayList<CuisinePrefEntity>();
            for (CuisineType c : cuisineTypeList) {
                CuisinePrefEntity newCuisinePref = new CuisinePrefEntity();
                newCuisinePref.setCuisineType(c);
                newCuisinePrefList.add(newCuisinePref);
            }
            if (!touristAcctState.getTourist().getPersonalPref().getCuisinePrefs().equals(newCuisinePrefList)) {
                hasNewUpdate = true;
                hasPreferenceUpdate = true;
                System.out.println("here 1");
            }
            
            List<InterestPrefEntity> newInterestPrefList = new ArrayList<InterestPrefEntity>();
            for (Interest i : interestList) {
                InterestPrefEntity newInterestPref = new InterestPrefEntity();
                newInterestPref.setInterest(i);
                newInterestPrefList.add(newInterestPref);
            }
            if (!touristAcctState.getTourist().getPersonalPref().getCuisinePrefs().equals(newCuisinePrefList)) {
                hasNewUpdate = true;
                hasPreferenceUpdate = true;
                System.out.println("here 2");
            }
            
            
            if (hasNewUpdate == true) {
                // update
                touristAccountMgr.updateTouristAccount(touristAccountId, latestPassword);
                touristAccountMgr.updateTourist(touristAcctState.getTourist().getId(), country, language.toString(), emailSecondary);
                
                if (hasPreferenceUpdate == true) {
                    touristAccountMgr.updateTouristPersonalPrefs(touristAcctState.getTourist().getId(), newCuisinePrefList, newInterestPrefList);
                }
                statusMessage = systemMessages.getSystemMessage("UPDATE_SUCCESS", language);
//                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, statusMessage, ""));
                // send status message to next page
                ctx.getExternalContext().getSessionMap().put("statusMessageFromEdit", statusMessage);
                
                localization.putSavedLocaleToSession(language);
                reset();
                redirect.goTouristWelcomePage();
            }
            else {
                if (passwordChecking == false) {
                    statusMessage = systemMessages.getSystemMessage("UPDATE_NO_CHANGES", preferredLocale);
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, statusMessage, ""));
                }
            }
        }
        catch (ExistException ex) {
//            System.out.println(ex.getMessage());
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, ex.getMessage(), ""));
        }
        catch (Exception ex) {
            ex.printStackTrace();
//            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, ex.getMessage(), ""));
        }
    }

    private void reset() {
        currentPassword = "";
        newPassword = "";
        confirmPassword = "";
    }

    public TouristAccountSessionBean getTouristAccountMgr() {
        return touristAccountMgr;
    }

    public void setTouristAccountMgr(TouristAccountSessionBean touristAccountMgr) {
        this.touristAccountMgr = touristAccountMgr;
    }

    public FacesContext getCtx() {
        return ctx;
    }

    public void setCtx(FacesContext ctx) {
        this.ctx = ctx;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public SystemMessagesBean getSystemMessages() {
        return systemMessages;
    }

    public void setSystemMessages(SystemMessagesBean systemMessages) {
        this.systemMessages = systemMessages;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPreferredLocale() {
        return preferredLocale;
    }

    public void setPreferredLocale(String preferredLocale) {
        this.preferredLocale = preferredLocale;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getEmailSecondary() {
        return emailSecondary;
    }

    public void setEmailSecondary(String emailSecondary) {
        this.emailSecondary = emailSecondary;
    }

    public Long getTouristAccountId() {
        return touristAccountId;
    }

    public void setTouristAccountId(Long touristAccountId) {
        this.touristAccountId = touristAccountId;
    }

    public TouristAccountState getTouristAcctState() {
        return touristAcctState;
    }

    public void setTouristAcctState(TouristAccountState touristAcctState) {
        this.touristAcctState = touristAcctState;
    }

    public WebLocalization getLocalization() {
        return localization;
    }

    public void setLocalization(WebLocalization localization) {
        this.localization = localization;
    }

    public String getConfirmPassword() {
        return confirmPassword;
    }

    public void setConfirmPassword(String confirmPassword) {
        this.confirmPassword = confirmPassword;
    }

    public String getNewPassword() {
        return newPassword;
    }

    public void setNewPassword(String newPassword) {
        this.newPassword = newPassword;
    }

    public Country getCountry() {
        return country;
    }

    public void setCountry(Country country) {
        this.country = country;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getBirthdate() {
        return birthdate;
    }

    public void setBirthdate(String birthdate) {
        this.birthdate = birthdate;
    }

    public String getLanguage() {
        return language;
    }

    public void setLanguage(String language) {
        this.language = language;
    }

    public String getCurrentPassword() {
        return currentPassword;
    }

    public void setCurrentPassword(String currentPassword) {
        this.currentPassword = currentPassword;
    }

    public PageRedirectorBean getRedirect() {
        return redirect;
    }

    public void setRedirect(PageRedirectorBean redirect) {
        this.redirect = redirect;
    }

    public MenuModel getTouristMainMenuModel() {
        return touristMainMenuModel;
    }

    public void setTouristMainMenuModel(MenuModel touristMainMenuModel) {
        this.touristMainMenuModel = touristMainMenuModel;
    }

    public MenuModel getTouristNavMenuModel() {
        return touristNavMenuModel;
    }

    public void setTouristNavMenuModel(MenuModel touristNavMenuModel) {
        this.touristNavMenuModel = touristNavMenuModel;
    }

    public List<CuisineType> getCuisineTypeList() {
        return cuisineTypeList;
    }

    public void setCuisineTypeList(List<CuisineType> cuisineTypeList) {
        this.cuisineTypeList = cuisineTypeList;
    }

    public List<Interest> getInterestList() {
        return interestList;
    }

    public void setInterestList(List<Interest> interestList) {
        this.interestList = interestList;
    }
}